//
// Created by ttao on 2022/8/4.
//

#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <unix/tcp_log.h>
#include "container.h"
#define ISNULL(node) (!node || node == NULL)
#define ISNOTNULL(node) (!ISNULL(node))
/* ================ start of Stack.c ================ */
/*
 * eg:  初始化栈
        stack s;
        char *c[100];
        initStack(&s, c, sizeof(c)/sizeof(char *));
 */
//清空栈
void stack_clear(stack *s)
{
    while(s->point!=0)
    {
        s->head[s->point-1] = NULL;
        s->point--;
    }
}
//堆栈是否为空
int isempty(stack *s)
{
    return(s->point == 0);
}
//入栈函数
int push(stack *s, void *node)
{
    if(s->point < s->maxlen)
    {
        s->head[(s->point)++] = node;
        return(0);
    }
    else
        return(-1);
}
//出栈函数
void *pop(stack *s)
{
    if(s->point >0)
        return(s->head[--(s->point)]);
    else
        return(0);
}
/* ================ end of Stack.c ================ */

/* ================ start of Queue.c ================ */
/*
 *  eg: 队列
    struct Queue queue;
    initQueue(&queue, 100);

    add(queue, dtsnew("hello"));
    dts dts1 = (dts)get(&queue);
 */
struct Queue *initQueue(struct Queue *queue, int MAXSIZE)
        /*初始化队列*/
{
    queue->maxsize = MAXSIZE;
    queue->size = 0;
    queue->first = NULL;
    queue->last = &(queue->first);
    pthread_rwlock_init(&queue->rwlock, NULL);
    return queue;
}

/**
 * 向队列中加入任务
 * @param ttq
 * @param task
 */
static inline void Insert_Task_To_Queue(struct Queue *queue, queue_task_t *task)
{
    if(!queue || !task) return;
    if(ISNULL(queue->first))
        queue->first = task;
    *(queue->last) = task;
    queue->last = &task->next;
    atomicIncr(queue->size, 1);
}
// 任务出队
static inline queue_task_t* Get_Task_From_Queue(struct Queue *queue)
{
    queue_task_t *task = queue->first;
    if(ISNOTNULL(task))
    {
        queue->first = task->next;
        if (ISNULL(queue->first)) {
            queue->last = &queue->first;
        }
        atomicDecr(queue->size, 1);
    }
    return task;
}
void task_push(struct Queue *queue, void *task)
{
    if(ISNULL(queue))
        return;
    queue_task_t *q_task = (queue_task_t *)tcp_calloc(sizeof(queue_task_t));
    q_task->task = task;
    q_task->next = NULL;
    rwlock_wrlock(&queue->rwlock);
    Insert_Task_To_Queue(queue, q_task);
    rwlock_unlock(&queue->rwlock);
}
void* task_pop(struct Queue *queue)
{
    if(ISNULL(queue)) return NULL;
    rwlock_wrlock(&queue->rwlock);
    queue_task_t* q_task = Get_Task_From_Queue(queue);
    rwlock_unlock(&queue->rwlock);
    if(q_task) return q_task->task;
    return NULL;
}

void *popTaskBlock(struct Queue *queue) {          // 当队列为空时阻塞
    while (1) {
        void* val = task_pop(queue);
        if(ISNOTNULL(val))
            return val;
    }
}
/* ================ end of Queue.c ================ */


/* ================ end of Lists.c ================ */
void initLinkList(linklist_t *list)                 // 初始化链表
{
    list->size = 0;
    list->head = NULL;
    list->tail = NULL;
}
static inline void insertnode(linklist_t *list, table_t *tb, table_t *itb, enum InsertType type)  // 插入元素
{
    list->size++;
    if(ISNULL(list->head) && ISNULL(list->tail) && ISNULL(itb)) // 首次插入
    {
        list->head = list->tail = tb;
        return;
    }
    switch (type) {
        case BEFORE:
            tb->next = itb;
            tb->prev = itb->prev;
            if(ISNULL(itb->prev))
                list->head = tb;
            itb->prev = tb;
            break;
        case AFTER:
            tb->next = itb->next;
            tb->prev = itb;
            if(ISNULL(itb->next))
                list->tail = tb;
            itb->next = tb;
            break;
    }
}
void inserttable(linklist_t *list, void *val, table_t *itb, enum InsertType type)
{
    if(ISNULL(itb) || ISNULL(list)) return;
    table_t *tb = (table_t *) malloc(sizeof(table_t));
    tb->value = val;
    tb->next = NULL;
    tb->prev = NULL;
    if(ISNOTNULL(tb))
        insertnode(list, tb, itb, type);
}
void addlinklisttable(linklist_t *list, void *val)          // 追加数据 后面插入
{
    if(ISNULL(list)) return;
    table_t *tb = (table_t *) malloc(sizeof(table_t));
    tb->value = val;
    tb->next = NULL;
    tb->prev = NULL;
    if(ISNOTNULL(tb))
        insertnode(list, tb, list->tail, AFTER);
}
void selmetatable(linklist_t *list)
{
    list->cursor = list->head;
}
int hasnext(linklist_t *list){
    if(ISNULL(list->cursor))
        return 0;
}
table_t *getTb(linklist_t *list)
{
    table_t * t = list->cursor;
    if(ISNOTNULL(t))
        list->cursor = list->cursor->next;
    return t;
}
void linklisteachinit(linklist_t *list)// 元素遍历
{
    selmetatable(list);
}
int destrylinklist(linklist_t *list, table_t *tb)                    // 销毁元素
{
    if(ISNOTNULL(tb->prev) && ISNOTNULL(tb->next))
    {
        tb->prev->next = tb->next;
        tb->next->prev = tb->prev;
    }
    if(ISNULL(tb->prev))
    {
        list->head = tb->next;
        if(ISNOTNULL(list->head))
            list->head->prev = NULL;
    }
    if(ISNULL(tb->next))
    {
        list->tail = tb->prev;
        if(ISNOTNULL(list->tail))
            list->tail->next = NULL;
    }
    list->size--;
    free(tb);
}
/* ================ start of Lists.c ================ */
